import numpy as np
from sklearn import datasets
from sklearn.metrics import accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
from tensorflow.keras import optimizers
from tensorflow.keras import regularizers
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
import matplotlib.pyplot as plt

# 加载数据
breast_cancer = datasets.load_breast_cancer()
x_train, x_test, y_train, y_test = train_test_split(
    breast_cancer.data,
    breast_cancer.target,
    test_size=0.3,
    random_state=420
)

# 定义感知器模型及训练函数
def threshold(x, d):
    return [1 if xi > d else 0 for xi in x]

def fit_perceptron(x, y, LearningRate, epoches, w, b):
    loss_history = []  # 记录每个epoch的损失值
    for step in range(epoches):
        for i in range(x.shape[0]):
            h = threshold(np.dot(w, x[i]) + b, 0)
            w = w + LearningRate * (y[i] - h) * x[i]
            b = b + LearningRate * (y[i] - h)
        loss = np.mean(np.square(y - threshold(np.dot(x, w) + b, 0)))  # 计算损失值
        loss_history.append(loss)
    return w, b, loss_history

# 定义神经网络模型
model = Sequential()
model.add(Dense(input_dim=x_train.shape[1],
                units=1,
                activation='sigmoid',
                kernel_regularizer=regularizers.l1(0.2)))
op = optimizers.RMSprop(learning_rate=0.0001)
model.compile(loss='mse', optimizer=op)

# 训练感知器模型并记录准确率
w_perceptron = np.random.random(x_train.shape[1])
b_perceptron = np.random.random(1)
w_perceptron, b_perceptron, loss_history_perceptron = fit_perceptron(
    x_train, y_train, 0.001, 2000, w_perceptron, b_perceptron)

pred_train_perceptron = threshold(np.dot(x_train, w_perceptron) + b_perceptron, 0)
pred_test_perceptron = threshold(np.dot(x_test, w_perceptron) + b_perceptron, 0)

acc_train_perceptron = accuracy_score(y_train, pred_train_perceptron)
acc_test_perceptron = accuracy_score(y_test, pred_test_perceptron)

confusion_matrix_perceptron = confusion_matrix(y_test, pred_test_perceptron)

print("Final perceptron weights:")
print(w_perceptron)

print('Perceptron Accuracy (Train):', acc_train_perceptron)
print('Perceptron Accuracy (Test):', acc_test_perceptron)
print('Perceptron Confusion Matrix:\n', confusion_matrix_perceptron)

# 训练神经网络模型并记录准确率
loss_history_nn = []
for epoch in range(20000):
    cost = model.train_on_batch(x_train, y_train)
    if epoch % 1000 == 0:
        print("epoch %d,cost:%f" % (epoch, cost))
    loss_history_nn.append(cost)

pred_train_nn = threshold(model.predict(x_train), 0.5)
pred_test_nn = threshold(model.predict(x_test), 0.5)

acc_train_nn = accuracy_score(y_train, pred_train_nn)
acc_test_nn = accuracy_score(y_test, pred_test_nn)

confusion_matrix_nn = confusion_matrix(y_test, pred_test_nn)

final_weights = model.get_weights()

# 输出各层的权重值
for i, layer_weights in enumerate(final_weights):
    print(f"Weights of Layer {i}:")
    print(layer_weights)
    print()

print('Neural Network Accuracy (Train):', acc_train_nn)
print('Neural Network Accuracy (Test):', acc_test_nn)
print('Neural Network Confusion Matrix:\n', confusion_matrix_nn)

# 绘制感知器的收敛曲线
plt.figure(figsize=(8, 6))
plt.plot(loss_history_perceptron)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Perceptron Convergence Curve')
plt.show()

# 绘制神经网络的收敛曲线
plt.figure(figsize=(8, 6))
plt.plot(loss_history_nn)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Neural Network Convergence Curve')
plt.show()